#pragma once

#include <iostream>
#include <string>

#include <cstring>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

const int NUM = 1024;

enum
{
    USAGE_ERR = 1,
    SOCK_ERR,
    CONNECT_ERR
};

namespace yzc_client
{
    using namespace std;
    class TcpClient
    {
    public:
        TcpClient(const string &ip, const uint16_t &port)
            : _sockfd(-1), _serverip(ip), _serverport(port) {}

        void InitClient()
        {
            // 1.创建套接字
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_sockfd < 0)
            {
                cerr << "client creat socket error" << endl;
                exit(SOCK_ERR);
            }
            else
                cout << "client creat socket success" << endl;

            // 2. bind udp客户端不需要显示bind，tcp客户端也不需要显示bind
            // client的port需要让客户端自行选择

            // 3.客户端需不需要listen? 客户端不需要监听连接
            // 4.客户打需不需要accept? 不需要accept

            // 5. 客户端需要什么？ 需要发起连接
        }

        void start()
        {
            // 5. 创建通信结构体,并填入连接对方的信息。然后使用connect发起连接
            struct sockaddr_in server;
            memset(&server, 0, sizeof(server));

            server.sin_family = AF_INET;
            server.sin_port = htons(_serverport);
            server.sin_addr.s_addr = inet_addr(_serverip.c_str());

            if (connect(_sockfd, (struct sockaddr *)&server, sizeof(server)) < 0)
            {
                cerr << "client connect error" << endl;
            }
            else
            {
                // 6.连接成功，可以通信
                string msg;
                while (true)
                {
                    std::cout << "please enter:";
                    getline(cin, msg); // 会自动清空\n
                    write(_sockfd, msg.c_str(), msg.size());

                    char buffer[NUM];
                    int n = read(_sockfd, buffer, sizeof(buffer) - 1);
                    if (n > 0)
                    {
                        // 目前将读取的数据当前字符串
                        buffer[n] = 0;
                        cout << "Server回显:" << buffer << endl;
                    }
                    else
                    {
                        // 说明服务端关闭了数据，我直接退出
                        break;
                    }
                }
            }
        }

        ~TcpClient()
        {
            if (_sockfd > 0)
                close(_sockfd);
        }

    private:
        int _sockfd;          // 套接字
        string _serverip;     // 对方服务器ip
        uint16_t _serverport; // 对方服务器端口
    };
}